#ifndef SIGNAL_H_
#define SIGNAL_H_

#include <Basic.hh>

/**
 * 시그널 종류.
 */
enum SignalType
{
	CondVarType
};

//
/**
 * \file Signal.hh
 * \author  jsk <jsk.jinsubkim@gmail.com>
 * \version 1.0
 *
 * \class Signal Signal.hh
 *
 * 스레드 간에 실행 순서를 보장한다.
 * 
 * 즉, 어떤 작업에 앞서 선행되어야할 작업이 있다면, pend 메소드를 통해서 
 * 신호를 기다린다. 선행되어야할 작업이 끝났을 때 post 메소드를 통해서 
 * 신호를 보낸다.
 */
class Signal
{
public:
	/**
	 * \name generate
	 * 
	 * Signal factory
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	static Signal* generate(SignalType Type);
	
	/**
	 * \name post
	 * 
	 * 신호를 보낸다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf post() = 0;
	
	/**
	 * \name pend
	 * 
	 * 신호를 기다린다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 
	 */
	virtual ResultOf pend() = 0;
	
	/**
	 * \name setTimeout
	 * \param WaitingTime 대기 시간.
	 * 
	 * 대기시간을 설정한다.
	 * 
	 * WaitingTime = 0인 경우, 
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf setTimeout(Number WaitingTime) = 0;
	
	/**
	 * \name release
	 * 
	 * 시그널을 기다리고 있는 스레드들을 해방한다.
	 * 
	 * \warning
	 * 
	 * 실제 신호를 받아서 깨어나는 경우와 release 메소드를 통해서 깨어나는 
	 * 경우를 구분하지 않는다. 이는 브로드 캐스팅으로 사용할 수 있도록 하기 
	 * 위함이다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf release() = 0;
	
	/**
	 * \name preventWaiting
	 * 
	 * 시그널을 기다리는 행위를 방지한다. 
	 * 단, 이미 발생한 시그널에 대해서는 pend 메소드를 통해서 처리할 수 있다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf preventWaiting() = 0;
	
	/**
	 * \name allowWaiting
	 * 
	 * 시그널을 기다릴 수 있도록 한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf allowWaiting() = 0;
	
	/**
	 * \name init
	 * 
	 * 시그널을 초기화 한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf init() = 0;
	
	/**
	 * \name tellWaiting
	 * 
	 * 대기하는 스레드드의 개수를 알려준다.
	 * 
	 * \return 
	 * 
	 * 대기하는 스레드의 개수.
	 * 양수 일경우 대기자가 있는 경우, 
	 * 음수일 경우 시그널이 발생한 경우.
	 */
	virtual Number tellWaiting() = 0;
};

#endif //SIGNAL_H_